﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Security.Claims;
using Yz.Base;
using Yz.Base.Enums;
using Yz.Core.Extensions;
using Yz.Core.Tools;
using Yz.Model.Constants;
using Yz.Model.Enums;

namespace Yz.Web.Controllers
{
    [Authorize]
    public class BaseController : Controller
    {
        #region Excel导出
        /// <summary>
        /// Excel导出
        /// </summary>
        /// <param name="npoiExcel"></param>
        /// <param name="excelName"></param>
        protected FileResult ExportExcel(NPOIExcel npoiExcel)
        {
            MemoryStream stream = YzNPOI.ExportExcel(npoiExcel);
            var provider = new FileExtensionContentTypeProvider();
            string fileExt = "";
            if (npoiExcel.ExcelType == ExcelType.Xlsx)
            {
                fileExt = ExcelSuffix.Xlsx;
            }
            else
            {
                fileExt = ExcelSuffix.Xls;
            }
            if (npoiExcel.ExcelName.Contains("."))
            {
                npoiExcel.ExcelName = npoiExcel.ExcelName.Substring(0, npoiExcel.ExcelName.LastIndexOf("."));
            }
            npoiExcel.ExcelName += fileExt;
            // npoiExcel.ExcelName = WebUtility.UrlEncode(npoiExcel.ExcelName);
            var contentType = provider.Mappings[fileExt];
            ///Response.Headers.Add("fileName", npoiExcel.ExcelName);
            Response.Headers.Append("Content-Disposition", "attachment; filename=" + WebUtility.UrlEncode(npoiExcel.ExcelName));
            //支持跨域时可以通过axios等http库获取到在header中的数据
            //Response.Headers.Add("Access-Control-Expose-Headers", "fileName");
            return File(stream.ToArray(), contentType, npoiExcel.ExcelName);
        }
        #endregion

        #region 用户属性
        /// <summary>
        /// 公司ID
        /// </summary>
        protected int CompanyId
        {
            get
            {
                var claim = User;
                return claim.FindFirst(ClaimTypes.Email).Value.ToInt();
            }
        }
        /// <summary>
        /// 用户Id
        /// </summary>
        protected int UserId { get => GetUserId(); }
        /// <summary>
        /// 用户姓名
        /// </summary>
        protected string UserName
        {
            get => User.Identity.Name;
        }
        protected int GetUserId()
        {
            var claim = User;
            var userId = 0;
            if (claim.HasClaim(c => c.Type == ClaimTypes.NameIdentifier))
            {
                userId = claim.FindFirst(ClaimTypes.NameIdentifier).Value.ToInt();
            }
            else if (claim.HasClaim(c => c.Type == JwtRegisteredClaimNames.Jti))
            {
                userId = claim.FindFirst(JwtRegisteredClaimNames.Jti).Value.ToInt();
            }
            return userId;
        }
        protected List<string> GetRoleList(UserType ut)
        {
            List<string> roleList = new List<string>();
            switch (ut)
            {
                case UserType.Admin:
                    roleList.Add(UserRoleName.Admin);
                    roleList.Add(UserRoleName.Manager);
                    break;
                case UserType.CompanyAdmin:
                    roleList.Add(UserRoleName.CompanyAdmin);
                    roleList.Add(UserRoleName.Manager);
                    roleList.Add(UserRoleName.Company);
                    break;
                default:
                    roleList.Add(UserRoleName.Staff);
                    roleList.Add(UserRoleName.Company);
                    break;
            }
            return roleList;
        }
        #endregion

        #region 文件上传
        /// <summary>
        /// 文件根路径
        /// </summary>
        protected string FileRootPath
        {
            get
            {
                var dtNow = DateTime.Now;
                return "/File" + DateTime.Now.Year + "/" + dtNow.ToString("yyyyMMdd") + "/u" + UserId + "/";
            }

        }
        /// <summary>
        /// 临时文件根路径
        /// </summary>
        protected string TempFileRootPath
        {
            get
            {
                var dtNow = DateTime.Now;
                return "/FilesTemp/u" + UserId + "/" + dtNow.ToString("yyyyMM") + dtNow.ToString("yyyyMMdd") + "/";
            }
        }
        /// <summary>
        /// 合并文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        protected VmUpFile MergeFile(IWebHostEnvironment webHostEnv, string fileName, string guid)
        {
            var flExtension = fileName.Substring(fileName.LastIndexOf('.')).ToLower();
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var fileRootPath = FileRootPath;
            var tempFilePath = webHostEnv.WebRootPath + tempFileRootPath + guid.Replace("-", "") + "/";
            if (!Directory.Exists(tempFilePath))
            {
                upFile.Suc = false;
                upFile.Msg = "文件上传失败！";
                upFile.Chunk = false;
                return upFile;
            }
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            if (!Directory.Exists(webHostEnv.WebRootPath + fileRootPath))
            {
                Directory.CreateDirectory(webHostEnv.WebRootPath + fileRootPath);
            }
            var targetPath = Path.Combine(webHostEnv.WebRootPath + fileRootPath, newFileName + flExtension);///合并后的文件路径

            var dcInfo = new DirectoryInfo(tempFilePath);
            var files = dcInfo.GetFiles();
            MergeTempFile(targetPath, files);
            if (files.Length == 0)
            {
                upFile.Suc = false;
                upFile.Msg = "文件上传失败！";
                return upFile;
            }

            upFile.Suc = true;
            upFile.Msg = "上传成功";
            upFile.File = new FileUp()
            {
                Name = fileName,
                Path = fileRootPath + newFileName + flExtension,
                FileSuffix = flExtension,
                FileType = FileType.Vdo,
                ThPath = FileThPath.Vdo
            };
            return upFile;
        }

        /// <summary>
        /// 合并临时文件
        /// </summary>
        /// <param name="targetPath"></param>
        /// <param name="files"></param>
        private void MergeTempFile(string targetPath, FileInfo[] files)
        {
            foreach (var file in files.OrderBy(f => int.Parse(f.Name)))
            {
                using (var addFile = new FileStream(targetPath, FileMode.Append, FileAccess.Write))
                {
                    using (var AddWriter = new BinaryWriter(addFile))
                    {
                        //获得上传的分片数据流
                        using (Stream stream = file.Open(FileMode.Open))
                        {
                            using (var TempReader = new BinaryReader(stream))
                            {
                                //将上传的分片追加到临时文件末尾
                                AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 保存大文件
        /// </summary>
        /// <param name="chunk"></param>
        /// <param name="guid"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected VmUpFile SaveBigFile(IWebHostEnvironment webHostEnv, int chunk, string guid, IFormFile file)
        {
            //当前分片在上传分片中的顺序（从0开始） 
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var localPath = webHostEnv.WebRootPath + tempFileRootPath + guid.Replace("-", "") + "/";
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();

            if (!FileTypeList.VdoList.Contains(flExtension))
            {
                upFile.Suc = false;
                upFile.Msg = "只能上传Mp4、mov格式的文件！";
                return upFile;
            }
            using (var addFile = new FileStream(localPath + chunk, FileMode.Append, FileAccess.Write))
            {
                using (var AddWriter = new BinaryWriter(addFile))
                {
                    using (var stream = file.OpenReadStream())
                    {
                        using (var TempReader = new BinaryReader(stream))
                        {
                            //将上传的分片追加到临时文件末尾
                            AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
                        }
                    }
                }
            }
            upFile.File = new FileUp()
            {
                FileSuffix = flExtension,
                FileType = FileType.Vdo,
                Name = file.FileName
            };
            upFile.Msg = "分片上传中";
            upFile.Suc = true;
            return upFile;
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="ft"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected async Task<VmUpFile> SaveFile(IWebHostEnvironment webHostEnv, FileType ft, IFormFile file, int fileIndex = 1)
        {
            var upFile = new VmUpFile();
            //创建文件夹 
            string fileRootPath = FileRootPath;
            var localPath = webHostEnv.WebRootPath + fileRootPath;
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();
            #region 文件格式判断

            if (ft == FileType.Pic) //图片，判断图片格式的有效性
            {
                if (!FileTypeList.ImgList.Contains(flExtension))
                {
                    upFile.Suc = false;
                    upFile.Msg = "只能上传jpg,jpeg,png,bmp,gif格式的图片！";
                    return upFile;
                }
            }
            else if (ft == FileType.Doc)
            {
                if (!FileTypeList.DocList.Contains(flExtension))
                {
                    upFile.Suc = false;
                    upFile.Msg = "只能上传pdf格式的文档！";
                    return upFile;
                }
            }
            else if (ft == FileType.Vdo)
            {
                if (!FileTypeList.VdoList.Contains(flExtension))
                {
                    upFile.Suc = false;
                    upFile.Msg = "只能上传mp4、mov格式的视频！";
                    return upFile;
                }
            }
            else
            {
                upFile.Suc = false;
                upFile.Msg = "只能上传文档、图片和视频文件！";
                return upFile;
            }

            #endregion 文件格式有效性判断

            //保存原文件
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var filePath = string.Format("{0}{1}{2}", fileRootPath, newFileName, flExtension);
            var fileLocalPath = string.Format("{0}{1}{2}", localPath, newFileName, flExtension);

            var fileThPath = ""; //缩略图路径
            upFile.Suc = true;
            using (var fileStream = new FileStream(fileLocalPath, FileMode.Create, FileAccess.Write))
            {
                await file.CopyToAsync(fileStream);
                fileStream.Flush(true);
            }
            #region 图片

            if (FileTypeList.ImgList.Contains(flExtension)) //保存缩略图
            {
                var newThumbnailFileName = newFileName + "_th";
                fileThPath = string.Format("{0}{1}{2}", fileRootPath, newThumbnailFileName, flExtension);

                // var thFileLocalPath = string.Format("{0}{1}{2}", localPath, newThumbnailFileName, flExtension);
                // ImageProcessor.SaveImage(file.InputStream, fileLocalPath, thFileLocalPath);
            }

            #endregion

            else
            {
                #region 文档

                if (FileTypeList.DocList.Contains(flExtension)) //文档
                {
                    fileThPath = FileThPath.PDF;
                }

                #endregion

                #region 视频文件

                else if (FileTypeList.VdoList.Contains(flExtension))
                {
                    fileThPath = FileThPath.Vdo;
                }

                #endregion 视频文件

                else
                {
                    upFile.Suc = false;
                    upFile.Msg = "只能上传文档、图片和视频！";
                }
            }
            upFile.Suc = true;
            upFile.Msg = "上传成功";
            upFile.File = new FileUp()
            {
                Name = file.FileName,
                FileSuffix = flExtension,
                ThPath = fileThPath,
                FileType = ft,
                Path = filePath,
                Index = fileIndex
            };
            return upFile;
        }

        /// <summary>
        /// 保存临时文件
        /// </summary>
        /// <param name="ft"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected async Task<VmUpFile> SaveTempFile(IWebHostEnvironment webHostEnv, FileType ft, IFormFile file)
        {
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var localPath = webHostEnv.WebRootPath + tempFileRootPath;
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();

            #region 文件格式有效性判断

            if (ft == FileType.Pic) //图片，判断图片格式的有效性
            {
                if (!FileTypeList.ImgList.Contains(flExtension))
                {
                    upFile.Suc = false;
                    upFile.Msg = "只能上传jpg,jpeg,png,bmp,gif格式的图片！";
                    return upFile;
                }
            }
            else if (ft == FileType.Doc)
            {
                if (!FileTypeList.DocList.Contains(flExtension))
                {
                    upFile.Suc = false;
                    upFile.Msg = "只能上传pdf,doc,docx格式的文档！";
                    return upFile;
                }
            }
            else if (ft == FileType.Vdo)
            {
                upFile.Suc = false;
                upFile.Msg = "只能上传mp4,mov格式的视频！";
                return upFile;
            }
            else
            {
                upFile.Suc = false;
                upFile.Msg = "只能上传文档、图片和视频！";
                return upFile;
            }

            #endregion 文件格式有效性判断

            //保存原文件
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var filePath = string.Format("{0}{1}{2}", tempFileRootPath, newFileName, flExtension);
            var fileLocalPath = string.Format("{0}{1}{2}", localPath, newFileName, flExtension);
            //保存原文件
            using (var stream = new FileStream(fileLocalPath, FileMode.Create))
            {

                await file.CopyToAsync(stream);
            }
            upFile.Suc = true;
            upFile.Msg = "上传成功";
            upFile.File = new FileUp()
            {
                Name = file.FileName,
                Path = filePath,
                FileSuffix = flExtension,
                FileType = ft
            };
            return upFile;
        }
        #endregion

        #region 验证码
        /// <summary>
        /// 获得验证码
        /// </summary>
        /// <returns></returns>
        public string GetSessionCheckCode()
        {
            string checkCode = "";
            var sessCode = HttpContext.Session.GetString(BaseSessionConstant.CheckCode);
            if (sessCode != null)
            {
                checkCode = sessCode.ToString();
            }
            return checkCode;
        }
        /// <summary>
        /// 移除验证码
        /// </summary>
        protected void RemoveSessionCheckCode()
        {
            HttpContext.Session.Remove(BaseSessionConstant.CheckCode);
        }
        /// <summary>
        /// 设置验证码
        /// </summary>
        /// <param name="checkCode"></param>
        protected void SetSessionCheckCode(string checkCode)
        {
            HttpContext.Session.SetString(BaseSessionConstant.CheckCode, checkCode);
        }
        /// <summary>
        /// 验证验证码是否正确
        /// </summary>
        /// <param name="checkCode"></param>
        /// <returns></returns>
        protected bool ValidateCheckCode(string checkCode)
        {
            string sessionCode = GetSessionCheckCode(); 
            return checkCode.ToLower() == sessionCode.ToLower();
        }
        /// <summary>
        /// 生成随机数
        /// </summary>
        /// <param name="len"></param>
        /// <returns></returns>
        protected string GetRandomNum(int len)
        {
            Random rnd = new Random();
            //验证码的字符集，去掉了一些容易混淆的字符 
            char[] character = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
            string InviteCode = "";
            //生成验证码字符串 
            for (int i = 0; i < len; i++)
            {
                InviteCode += character[rnd.Next(character.Length)];
            }
            return InviteCode;
        }
        #endregion
    }
}